package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	
	"github.com/xfio/internal/db"
	"github.com/xfio/internal/models"
	"strconv"
)

func main() {
	// 确保在正确的目录下运行
	currentDir := "/home/xfio"
	if err := os.Chdir(currentDir); err != nil {
		log.Printf("Could not change to directory %s: %v", currentDir, err)
	}

	database, err := db.NewDB("fio_test.db")
	if err != nil {
		log.Fatal(err)
	}
	defer database.Close()

	// 启动后台心跳检查定时器
	go func() {
		ticker := time.NewTicker(30 * time.Second) // 每30秒检查一次
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				if err := database.CheckWorkerHeartbeatTimeouts(); err != nil {
					log.Printf("Error checking worker heartbeat timeouts: %v", err)
				}
			}
		}
	}()

	r := gin.Default()

	// 设置Web界面路由（API路由之前）
	setupWebRoutes(r, database)

	// API路由组 - 所有API端点都以/api开头
	api := r.Group("/api")
	{
		// API根端点
		api.GET("/", func(c *gin.Context) {
			c.JSON(http.StatusOK, gin.H{"message": "FIO Test Controller API"})
		})

		// Worker相关API
		api.POST("/workers/register", func(c *gin.Context) {
			var reg models.WorkerRegistration
			if err := c.ShouldBindJSON(&reg); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}

			// 添加调试信息
			// log.Printf("Received registration request: Name=%s, IP=%s, FIOVersion=%s", reg.Name, reg.IPAddress, reg.FIOVersion)

			// 检查是否已存在相同名称和IP的Worker
			existingWorker, err := database.GetWorkerByNameAndIP(reg.Name, reg.IPAddress)
			if err != nil && err.Error() != "sql: no rows in result set" {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			
			var worker models.Worker
			if err == nil && existingWorker != nil {
				// 已存在的Worker，更新状态
				worker = models.Worker{
					ID:                           existingWorker.ID,
					Name:                         reg.Name,
					IPAddress:                    reg.IPAddress,
					Status:                       "online",
					HeartbeatStatus:              "healthy", // 默认为健康
					LastHeartbeat:                time.Now(),
					CreatedAt:                    existingWorker.CreatedAt,
					ConsecutiveHeartbeatFailures: 0, // 重置失败计数
					ConsecutiveHeartbeatSuccess:  3, // 刚注册的Worker设为3次成功
				FIOStatus:                    "stopped", // 默认为停止状态
					FIOVersion:                   reg.FIOVersion, // 设置 fio 版本
				}
			} else {
				// 新的Worker，创建记录
				worker = models.Worker{
					ID:                           uuid.New().String(),
					Name:                         reg.Name,
					IPAddress:                    reg.IPAddress,
					Status:                       "online",
					HeartbeatStatus:              "healthy", // 默认为健康
					LastHeartbeat:                time.Now(),
					CreatedAt:                    time.Now(),
					ConsecutiveHeartbeatFailures: 0,
					ConsecutiveHeartbeatSuccess:  3, // 新注册的Worker设为3次成功
				FIOStatus:                    "stopped", // 默认为停止状态
					FIOVersion:                   reg.FIOVersion, // 设置 fio 版本
				}
			}

			if err := database.RegisterWorker(worker); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, worker)
		})

		api.GET("/workers", func(c *gin.Context) {
			workers, err := database.GetWorkers()
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, workers)
		})

		api.GET("/workers/:id", func(c *gin.Context) {
			id := c.Param("id")
			_, err := database.GetWorker(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Worker not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			worker, err := database.GetWorker(id)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			c.JSON(http.StatusOK, worker)
		})

		api.POST("/workers/:id/heartbeat", func(c *gin.Context) {
			id := c.Param("id")
			
			_, err := database.GetWorker(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Worker not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			// 尝试解析请求体以获取系统和磁盘信息
			var systemInfo models.SystemInfo
			var diskInfo []models.DiskInfo
			var fioVersion string
			var fioStatus string
			if c.Request.Body != nil {
				// 尝试解析系统信息和磁盘信息
				var heartbeatData map[string]interface{}
				if err := c.ShouldBindJSON(&heartbeatData); err == nil {
					// 如果请求包含系统和磁盘信息，则解析
					if sysInfo, exists := heartbeatData["system_info"]; exists {
						if sysInfoMap, ok := sysInfo.(map[string]interface{}); ok {
							// 转换系统信息
							if cpuInfo, ok := sysInfoMap["cpu_info"].(string); ok {
								systemInfo.CPUInfo = cpuInfo
							}
							if cpuCores, ok := sysInfoMap["cpu_cores"].(float64); ok {
								systemInfo.CPUCores = int(cpuCores)
							}
							if memoryTotal, ok := sysInfoMap["memory_total"].(float64); ok {
								systemInfo.MemoryTotal = int64(memoryTotal)
							}
							if memoryUsed, ok := sysInfoMap["memory_used"].(float64); ok {
								systemInfo.MemoryUsed = int64(memoryUsed)
							}
							if memoryFree, ok := sysInfoMap["memory_free"].(float64); ok {
								systemInfo.MemoryFree = int64(memoryFree)
							}
							if memoryPercent, ok := sysInfoMap["memory_percent"].(float64); ok {
								systemInfo.MemoryPercent = memoryPercent
							}
							if os, ok := sysInfoMap["os"].(string); ok {
								systemInfo.OS = os
							}
							if kernel, ok := sysInfoMap["kernel"].(string); ok {
								systemInfo.Kernel = kernel
							}
							if arch, ok := sysInfoMap["arch"].(string); ok {
								systemInfo.Arch = arch
							}
							if uptime, ok := sysInfoMap["uptime"].(float64); ok {
								systemInfo.Uptime = int64(uptime)
							}
						}
					}
					
					if diskList, exists := heartbeatData["disk_info"]; exists {
						if diskArray, ok := diskList.([]interface{}); ok {
							for _, diskItem := range diskArray {
								if diskMap, ok := diskItem.(map[string]interface{}); ok {
									var disk models.DiskInfo
									if name, ok := diskMap["name"].(string); ok {
										disk.Name = name
									}
									if mountPoint, ok := diskMap["mount_point"].(string); ok {
										disk.MountPoint = mountPoint
									}
									if totalSpace, ok := diskMap["total_space"].(float64); ok {
										disk.TotalSpace = int64(totalSpace)
									}
									if usedSpace, ok := diskMap["used_space"].(float64); ok {
										disk.UsedSpace = int64(usedSpace)
									}
									if freeSpace, ok := diskMap["free_space"].(float64); ok {
										disk.FreeSpace = int64(freeSpace)
									}
									if usedPercent, ok := diskMap["used_percent"].(float64); ok {
										disk.UsedPercent = usedPercent
									}
									if fileSystem, ok := diskMap["file_system"].(string); ok {
										disk.FileSystem = fileSystem
									}
									diskInfo = append(diskInfo, disk)
								}
							}
						}
					}
					
					// 解析 fio 版本信息
					if fioVer, exists := heartbeatData["fio_version"].(string); exists {
						fioVersion = fioVer
					}
					
					// 解析 fio 状态信息
					if fioStat, exists := heartbeatData["fio_status"].(string); exists {
						fioStatus = fioStat
					}
					
					// 添加调试日志
					// log.Printf("Received heartbeat data - fio_version: %s, fio_status: %s", fioVersion, fioStatus)
				}
			}

			// 创建完整的Worker信息用于存储系统和磁盘信息
			worker, err := database.GetWorker(id)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			
			worker.Status = "online"
			worker.HeartbeatStatus = "healthy"
			worker.LastHeartbeat = time.Now()
			worker.SystemInfo = &systemInfo
			worker.DiskInfo = diskInfo
			worker.FIOVersion = fioVersion  // 添加 fio 版本信息
			worker.FIOStatus = fioStatus    // 添加 fio 状态信息

			// 更新Worker信息，包括系统和磁盘信息
			if err := database.RegisterWorker(*worker); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			// 如果有系统和磁盘信息，更新Worker信息
			if systemInfo.CPUInfo != "" || len(diskInfo) > 0 {
				// 信息已存储在RegisterWorker中
			}

			c.JSON(http.StatusOK, gin.H{"status": "success", "worker_id": id})
		})

		// 删除Worker
		api.DELETE("/workers/:id", func(c *gin.Context) {
			id := c.Param("id")
			
			_, err := database.GetWorker(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Worker not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			if err := database.DeleteWorker(id); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "success", "message": "Worker removed"})
		})

		// 批量删除Worker
		api.POST("/workers/batch-delete", func(c *gin.Context) {
			var request struct {
				IDs []string `json:"ids"`
			}
			
			if err := c.ShouldBindJSON(&request); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}

			if len(request.IDs) == 0 {
				c.JSON(http.StatusBadRequest, gin.H{"error": "至少需要提供一个Worker ID"})
				return
			}

			deletedCount := 0
			var errors []string

			for _, id := range request.IDs {
				_, err := database.GetWorker(id)
				if err != nil {
					if err.Error() == "sql: no rows in result set" {
						errors = append(errors, fmt.Sprintf("Worker %s 不存在", id))
						continue
					}
					errors = append(errors, fmt.Sprintf("检查Worker %s 时出错: %v", id, err))
					continue
				}

				if err := database.DeleteWorker(id); err != nil {
					errors = append(errors, fmt.Sprintf("删除Worker %s 时出错: %v", id, err))
					continue
				}
				deletedCount++
			}

			status := "success"
			if len(errors) > 0 {
				status = "partial"
			}

			response := gin.H{
				"status": status,
				"deleted_count": deletedCount,
				"total_requested": len(request.IDs),
			}

			if len(errors) > 0 {
				response["errors"] = errors
			}

			c.JSON(http.StatusOK, response)
		})

		// 测试用例相关API
		api.POST("/test-cases", func(c *gin.Context) {
			var testCase models.TestCase
			if err := c.ShouldBindJSON(&testCase); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}

			testCase.ID = uuid.New().String()
			testCase.CreatedAt = time.Now()

			if err := database.CreateTestCase(testCase); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, testCase)
		})

		api.GET("/test-cases", func(c *gin.Context) {
			testCases, err := database.GetTestCases()
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, testCases)
		})

		// 模糊名称搜索测试用例：/api/test-cases/search?q=xxx&limit=20
		api.GET("/test-cases/search", func(c *gin.Context) {
			q := c.Query("q")
			limitStr := c.Query("limit")
			limit := 0
			if limitStr != "" {
				if v, err := strconv.Atoi(limitStr); err == nil && v > 0 {
					limit = v
				}
			}
			cases, err := database.GetTestCasesByName(q, limit)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			c.JSON(http.StatusOK, gin.H{"items": cases, "count": len(cases)})
		})

		api.GET("/test-cases/:id", func(c *gin.Context) {
			id := c.Param("id")
			testCase, err := database.GetTestCase(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Test case not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, testCase)
		})

		// 测试用例相关API - 更新测试用例
		api.PUT("/test-cases/:id", func(c *gin.Context) {
			id := c.Param("id")
			
			// 检查测试用例是否存在
			existingTestCase, err := database.GetTestCase(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Test case not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			var updatedTestCase models.TestCase
			if err := c.ShouldBindJSON(&updatedTestCase); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}

			// 保持原始ID和创建时间
			updatedTestCase.ID = id
			updatedTestCase.CreatedAt = existingTestCase.CreatedAt

			if err := database.UpdateTestCase(updatedTestCase); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, updatedTestCase)
		})

		// 测试用例相关API - 删除测试用例
		api.DELETE("/test-cases/:id", func(c *gin.Context) {
			id := c.Param("id")
			
			// 检查测试用例是否存在
			_, err := database.GetTestCase(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Test case not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			if err := database.DeleteTestCase(id); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "success", "message": "Test case deleted"})
		})

		// 测试用例：批量删除
		api.POST("/test-cases/batch-delete", func(c *gin.Context) {
			var req struct{ IDs []string `json:"ids"` }
			if err := c.ShouldBindJSON(&req); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}
			if len(req.IDs) == 0 {
				c.JSON(http.StatusBadRequest, gin.H{"error": "至少需要提供一个测试用例 ID"})
				return
			}
			deleted, err := database.BatchDeleteTestCases(req.IDs)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			c.JSON(http.StatusOK, gin.H{"status": "success", "deleted_count": deleted, "requested": len(req.IDs)})
		})

		// 任务相关API
		api.POST("/tasks/assign", func(c *gin.Context) {
			var assignment models.TaskAssignment
			if err := c.ShouldBindJSON(&assignment); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}

			var taskIDs []string

			// Normalize worker ID list from either new or old format
			var workerIDs []string
			if len(assignment.Workers) > 0 {
				for _, w := range assignment.Workers {
					if w.WorkerID != "" {
						workerIDs = append(workerIDs, w.WorkerID)
					}
				}
			}
			if len(workerIDs) == 0 && len(assignment.WorkerIDs) > 0 {
				workerIDs = append(workerIDs, assignment.WorkerIDs...)
			}

			if len(workerIDs) == 0 {
				c.JSON(http.StatusBadRequest, gin.H{"error": "No workers specified"})
				return
			}

			// 在真正创建任务之前，检查每个目标 worker 的在线状态和 fio server 状态
			var notReady []string
			for _, wid := range workerIDs {
				w, err := database.GetWorker(wid)
				if err != nil {
					// 如果数据库中找不到该 worker，认为未就绪
					if err.Error() == "sql: no rows in result set" {
						notReady = append(notReady, fmt.Sprintf("%s (not found)", wid))
						continue
					}
					c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
					return
				}

				// 期望 worker 在线且 fio_status 为 running/ready（具体状态可按需求扩展）
				if w.Status != "online" || (w.FIOStatus != "running" && w.FIOStatus != "ready") {
					notReady = append(notReady, fmt.Sprintf("%s (%s@%s, fio_status=%s)", w.Name, w.ID, w.IPAddress, w.FIOStatus))
				}
			}

			if len(notReady) > 0 {
				c.JSON(http.StatusBadRequest, gin.H{"error": "目标 Worker 上的 fio server 未就绪，请先在对应节点启动 fio server", "details": notReady})
				return
			}

			// 新行为：只创建一条任务记录，包含所有 worker_ids（WorkerID 字段保留为第一个 worker 以兼容旧逻辑）
			task := models.Task{
				ID:         uuid.New().String(),
				Name:       assignment.Name,
				TestCaseID: assignment.TestCaseID,
				WorkerID:   workerIDs[0],
				WorkerIDs:  workerIDs,
				Status:     "pending",
				CreatedAt:  time.Now(),
			}

			if err := database.AssignTask(task); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}
			taskIDs = append(taskIDs, task.ID)

			c.JSON(http.StatusOK, gin.H{"task_ids": taskIDs, "status": "assigned"})
		})

		api.GET("/tasks", func(c *gin.Context) {
			tasks, err := database.GetTasks()
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, tasks)
		})

		api.GET("/tasks/:id", func(c *gin.Context) {
			id := c.Param("id")
			task, err := database.GetTask(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, task)
		})

		api.DELETE("/tasks/:id", func(c *gin.Context) {
			id := c.Param("id")
			
			// 检查任务是否存在
			_, err := database.GetTask(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			if err := database.DeleteTask(id); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "deleted", "task_id": id})
		})

		api.POST("/tasks/:id/start", func(c *gin.Context) {
			id := c.Param("id")
			
			_, err := database.GetTask(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			if err := database.UpdateTaskStatus(id, "running"); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "started", "task_id": id})
		})

		api.POST("/tasks/:id/stop", func(c *gin.Context) {
			id := c.Param("id")
			_, err := database.GetTask(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			if err := database.StopTask(id); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "stopped", "task_id": id})
		})

		api.POST("/tasks/:id/complete", func(c *gin.Context) {
			id := c.Param("id")
			
			var result interface{}
			if err := c.ShouldBindJSON(&result); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}

			_, err := database.GetTask(id)
			if err != nil {
				if err.Error() == "sql: no rows in result set" {
					c.JSON(http.StatusNotFound, gin.H{"error": "Task not found"})
					return
				}
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			if err := database.CompleteTask(id, result); err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "completed", "task_id": id})
		})

		api.GET("/tasks/worker/:worker_id/pending", func(c *gin.Context) {
			workerID := c.Param("worker_id")
			tasks, err := database.GetPendingTasksForWorker(workerID)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, tasks)
		})

		// 结果分析API
		api.GET("/results/summary", func(c *gin.Context) {
			tasks, err := database.GetTasks()
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			var completedTasks []models.Task
			for _, task := range tasks {
				if task.Status == "completed" {
					completedTasks = append(completedTasks, task)
				}
			}

			c.JSON(http.StatusOK, gin.H{
				"results":         completedTasks,
				"total_completed": len(completedTasks),
			})
		})

		// 批量删除任务
		api.POST("/tasks/batch-delete", func(c *gin.Context) {
			var req struct{
				IDs []string `json:"ids"`
			}
			if err := c.ShouldBindJSON(&req); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}
			if len(req.IDs) == 0 {
				c.JSON(http.StatusBadRequest, gin.H{"error": "至少需要提供一个任务 ID"})
				return
			}

			deleted, err := database.BatchDeleteTasks(req.IDs)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			c.JSON(http.StatusOK, gin.H{"status": "success", "deleted_count": deleted, "requested": len(req.IDs)})
		})

		api.GET("/results/analysis/:test_case_id", func(c *gin.Context) {
			testCaseID := c.Param("test_case_id")
			tasks, err := database.GetCompletedTasksByTestCase(testCaseID)
			if err != nil {
				c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
				return
			}

			// 简单的性能数据聚合
			analysis := gin.H{
				"total_jobs": len(tasks),
				"workers":    make([]string, 0),
				"details":    tasks,
			}

			workers := make([]string, 0)
			for _, task := range tasks {
				workers = append(workers, task.WorkerID)
			}
			analysis["workers"] = workers

			c.JSON(http.StatusOK, analysis)
		})

		// Debug: 接收浏览器端上报的计时数据（临时端点）
		api.POST("/debug/client-timing", func(c *gin.Context) {
			var payload map[string]interface{}
			if err := c.ShouldBindJSON(&payload); err != nil {
				c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
				return
			}
			// 记录到服务端日志，供调试使用（不存入数据库）
			log.Printf("CLIENT_TIMING: %v", payload)
			c.Status(http.StatusNoContent)
		})
	}

	// 启动服务器
	log.Println("Starting xfio Controller on 0.0.0.0:8091")
	log.Fatal(r.Run("0.0.0.0:8091"))
}